<?php if(! defined('SYSPATH')) exit('No direct script access allowed');
/*
 +----------------------------------------------------------------------+
 | QuickPHP Framework Version 0.10                                      |
 +----------------------------------------------------------------------+
 | Copyright (c) 2010 QuickPHP.net All rights reserved.                 |
 +----------------------------------------------------------------------+
 | Licensed under the Apache License, Version 2.0 (the 'License');      |
 | you may not use this file except in compliance with the License.     |
 | You may obtain a copy of the License at                              |
 | http://www.apache.org/licenses/LICENSE-2.0                           |
 | Unless required by applicable law or agreed to in writing, software  |
 | distributed under the License is distributed on an 'AS IS' BASIS,    |
 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or      |
 | implied. See the License for the specific language governing         |
 | permissions and limitations under the License.                       |
 +----------------------------------------------------------------------+
 | Author: BoPo <ibopo@126.com>                                         |
 +----------------------------------------------------------------------+
*/
/**
 * 验证码显示以及验证类.
 *
 * @category    QuickPHP
 * @package     Captcha
 * @author      BoPo <ibopo@126.com>
 * @copyright   Copyright &copy; 2010 QuickPHP
 * @license     http://www.quickphp.net/license/
 * @version     $Id: Captcha.php 7240 2011-01-22 14:27:59Z bopo $
 */
class QuickPHP_Captcha
{
    protected static $_instance;
    protected static $counted;
    protected $driver = 'gd';

    public static $config = array
    (
        'style'      => 'basic',
        'width'      => 114,
        'height'     => 34,
        'complexity' => 4,
        'background' => '',
        'fontpath'   => 'fonts',
        'fonts'      => array('DejaVuSerif.ttf'),
        'promote'    => FALSE,
    );

    /**
     * 构建并返回一个新的验证码对象。
     *
     * @param   string  配置组名
     * @return  object
     */
    public static function factory($group = NULL, array $config = NULL)
    {
        if(empty(Captcha::$_instance))
            Captcha::$_instance = new Captcha($group, $config);

        return Captcha::$_instance;
    }

    /**
     * 建立了一个新的验证码对象。
     *
     * @param   string  配置组名
     * @return  void
     */
    public function __construct($group = NULL, array $config = NULL)
    {

        if ( ! is_string($group))
            $group = 'default';

        if ( ! is_array($config = QuickPHP::config('captcha')->$group))
            throw new QuickPHP_Captcha_Exception('undefined_group', array($group));

        if ($group !== 'default')
        {
            if ( ! is_array($default = QuickPHP::config('captcha')->get('default')))
                throw new QuickPHP_Captcha_Exception('undefined_group', array('default'));

            $config += $default;
        }

        foreach ($config as $key => $value)
        {
            if (array_key_exists($key, Captcha::$config))
                Captcha::$config[$key] = $value;
        }

        Captcha::$config['group'] = $group;

        if ( ! empty($config['background']))
        {
            Captcha::$config['background'] = str_replace('\\', '/', realpath($config['background']));

            if ( ! is_file(Captcha::$config['background']))
                throw new QuickPHP_Captcha_Exception('file_not_found', array(Captcha::$config['background']));
        }

        if ( ! empty($config['fonts']))
        {
            Captcha::$config['fontpath'] = str_replace('\\', '/', realpath($config['fontpath'])).'/';

            foreach ($config['fonts'] as $font)
            {
                if ( ! is_file(Captcha::$config['fontpath'].$font))
                    throw new QuickPHP_Captcha_Exception( 'file_not_found', array(Captcha::$config['fontpath'].$font));
            }
        }

        $driver = 'Captcha_Driver_'.ucfirst($config['style']);

        $this->driver = new $driver;

        if (!($this->driver instanceof Captcha_Abstract))
            throw new QuickPHP_Captcha_Exception('driver_implements', array($config['style'], get_class($this), 'Captcha_Interface'));
    }

    /**
     * 验证输入值是否与当前验证码值相同。
     *
     * @param   string   需要验证的验证码
     * @return  boolean
     */
    public static function valid($response)
    {
        if (Captcha::instance()->promoted()) return TRUE;

        $result = (bool) Captcha::instance()->driver->valid($response);

        if (Captcha::$counted !== TRUE)
        {
            Captcha::$counted = TRUE;

            if ($result === TRUE)
                Captcha::instance()->valid_count(Session::instance()->get('captcha_valid_count') + 1);
            else
                Captcha::instance()->invalid_count(Session::instance()->get('captcha_valid_count') + 1);
        }

        return $result;
    }

    /**
     * 返回或者设置的验证码应答次数
     *
     * @param   integer  new counter value
     * @param   boolean  trigger invalid counter (for internal use only)
     * @return  integer  counter value
     */
    public function valid_count($new_count = NULL, $invalid = FALSE)
    {
        $session = ($invalid === TRUE) ? 'captcha_valid_count' : 'captcha_valid_count';

        if ($new_count !== NULL)
        {
            $new_count = (int) $new_count;

            if ($new_count < 1)
                Session::instance()->delete($session);
            else
                Session::instance()->set($session, (int) $new_count);

            return (int) $new_count;
        }

        return (int) Session::instance()->get($session);
    }

    /**
     * 获得验证失效的次数
     *
     * @param   integer
     * @return  integer
     */
    public function invalid_count($new_count = NULL)
    {
        return $this->valid_count($new_count, TRUE);
    }

    /**
     * 复位应答次数
     *
     * @return  void
     */
    public function reset_count()
    {
        $this->valid_count(0);
        $this->valid_count(0, TRUE);
    }

    /**
     * Checks whether user has been promoted after having given enough valid responses.
     * 检查是否用户被提升为之后,给予足够的有效回复。
     *
     * @param   integer  valid response count threshold
     * @return  boolean
     */
    public function promoted($threshold = NULL)
    {
        if (Captcha::$config['promote'] === FALSE)
            return FALSE;

        if ($threshold === NULL)
            $threshold = Captcha::$config['promote'];

        return ($this->valid_count() >= $threshold);
    }

    /**
     * 返回或输出验证码
     *
     * @param   boolean  TRUE 则输出验证码, 样式. <img src="#" />
     * @return  mixed
     */
    public function render($html = TRUE)
    {
        return $this->driver->render($html);
    }

    /**
     * 魔术方法, 输出验证码
     *
     * @return  mixed
     */
    public function __toString()
    {
        return $this->render();
    }

}